module cl {
	export class StatusDO {

		private statusStack : string[];
		private statusChangedCbs : ((oldStatus : string, newStatus : string) => boolean)[];
		private statusChangedCbSenders : Object[];

		public constructor() {
			this.statusStack = [];
			this.statusChangedCbs = [];
			this.statusChangedCbSenders = [];
		}

		public currentStatus() : string {
			if (this.statusStack.length != 0) {
				return this.statusStack[this.statusStack.length - 1];
			}
			return "";
		}

		public findStatusGroup(status : string) : Number {
			if (status == "") {
				return 500;
			}
			for (let i = 0; i < status_json.length; i++) {
				if (status_json[i].indexOf(status) >= 0){
					return i;
				}
			}
			return -1;
		}

		/**
		 *  -1 : not found, 0 : same group, 1 : different group
		 */
		public mutexStatus(oldStatus : string, newStatus : string) : Number {
			let foundOld = oldStatus == "" ? 500 : -1;
			let foundNew = newStatus == "" ? 500 : -2;
			for (let i = 0; i < status_json.length; i++) {
				if (status_json[i].indexOf(newStatus) >= 0){
					foundNew = i;
				}
				if (status_json[i].indexOf(oldStatus) >= 0){
					foundOld = i;
				}
				if (foundOld > 0 && foundNew > 0){
					break;
				}
			}
			return foundNew == foundOld ? 0 : (foundOld < 0 || foundNew < 0 ? -1 : 1);
		}

		public pushStatus(status : string) : void {
			let oldStatus = this.currentStatus();
			if (status == oldStatus) {
				return;
			}

			// 实现同组互斥
			let mutex = this.mutexStatus(oldStatus, status);
			if (mutex == 1) {
				// 非同组状态
				this.statusStack.push(status);
			} else if (mutex == 0){
				// 同组互斥状态
				this.statusStack[this.statusStack.length - 1] = status;
			} else {
				return;
			}

			for (let i = 0; i < this.statusChangedCbs.length; i++) {
				if (this.statusChangedCbs[i].call(this.statusChangedCbSenders[i], oldStatus, status)) {
					break;
				}
			}
		}

		public popSameGroupStatusOf(status : string) : string {
			let current = this.currentStatus();
			if (this.mutexStatus(current, status) == 0) {
				return this.popStatus();
			}
			return "";
		}

		public popSomeStatus(status : string) : string {
			let current = this.currentStatus();
			if (current == status) {
				return this.popStatus();
			}
			return "";
		}

		public popStatus() : string {
			if (this.statusStack.length == 0) {
				return "";
			}
			let oldStatus = this.statusStack.pop();
			let status  = this.currentStatus();
			for (let i = 0; i < this.statusChangedCbs.length; i++) {
				if (this.statusChangedCbs[i].call(this.statusChangedCbSenders[i], oldStatus, status)) {
					break;
				}
			}
			return status;
		}

		public registerCb(cb : (oldStatus : string, newStatus : string) => boolean, sender : any) : void {
			this.statusChangedCbs.push(cb);
			this.statusChangedCbSenders.push(sender);
		}

		public unregisterCb(cb : (oldStatus : string, newStatus : string) => boolean, sender : any) : void {
			for (let i = this.statusChangedCbs.length -1; i >= 0; i--){
				if (this.statusChangedCbs[i] == cb){
					this.statusChangedCbs.splice(i, 1);
					this.statusChangedCbSenders.splice(i, 1);
				}
			}
		}
	}
}